/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						script_compound_expression.h

	$Header: /heroes4/script_compound_expression.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( SCRIPT_COMPOUND_EXPRESSION_H_INCLUDED )
#define SCRIPT_COMPOUND_EXPRESSION_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <cassert>
#include <iosfwd>

#include "counted_ptr.h"

// --------------------------------------------------------------------------
// t_script_unary_expression class template
// --------------------------------------------------------------------------

template < typename t_base, typename t_subexpression_arg >
class t_script_unary_expression : public t_base
{
public:
	// Types
	typedef t_subexpression_arg	t_subexpression;

	// Constructors
	t_script_unary_expression() {}
	t_script_unary_expression(
		t_script_unary_expression const &	other );

	// Member functions
	t_subexpression const &	get_subexpression() const;

	virtual bool			read( std::streambuf& stream, int verison);
	virtual bool			read_from_map(
								std::streambuf &	stream,
								int					format_version );
	virtual bool			write( std::streambuf& stream) const;

private:
	// Data members
	t_counted_ptr< t_subexpression > m_subexpression_ptr;
};

// --------------------------------------------------------------------------
// t_script_unary_expression members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
t_script_unary_expression< t_base, t_subexpression_arg >::t_script_unary_expression(
	t_script_unary_expression const &	other )
	:	t_base( other )
{
	if ( other.m_subexpression_ptr.get() != 0 )
		m_subexpression_ptr = other.m_subexpression_ptr->clone();
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
inline
typename t_script_unary_expression< t_base, t_subexpression_arg >::t_subexpression const &
t_script_unary_expression< t_base, t_subexpression_arg >::get_subexpression() const
{
	assert( m_subexpression_ptr.get() != 0 );
	return *m_subexpression_ptr;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
bool t_script_unary_expression< t_base, t_subexpression_arg >::read_from_map(
	std::streambuf &	stream,
	int					format_version )
{
	m_subexpression_ptr = t_subexpression::reconstruct_from_map( stream, format_version );
	return m_subexpression_ptr.get() != 0;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
bool t_script_unary_expression< t_base, t_subexpression_arg >::read( std::streambuf& stream, int version )
{
	m_subexpression_ptr = t_subexpression::reconstruct( stream, version );
	return m_subexpression_ptr.get() != 0;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
bool t_script_unary_expression< t_base, t_subexpression_arg >::write( std::streambuf& stream ) const
{
	if (!t_base::write( stream )) 
		return false;
	
	
	return m_subexpression_ptr->write( stream );
}

// --------------------------------------------------------------------------
// t_script_binary_expression class template
// --------------------------------------------------------------------------

template < typename t_base, typename t_subexpression_arg >
class t_script_binary_expression : public t_base
{
public:
	// Types
	typedef t_subexpression_arg	t_subexpression;

	// Constructors
	t_script_binary_expression() {}
	t_script_binary_expression(
		t_script_binary_expression const &	other );

	// Member functions
	t_subexpression const &	get_left_subexpression() const;
	t_subexpression const &	get_right_subexpression() const;

	virtual bool			read( std::streambuf& stream, int version );
	virtual bool			read_from_map(
								std::streambuf &	stream,
								int					format_version );
	virtual bool			write( std::streambuf& stream ) const;

private:
	// Data members
	t_counted_ptr< t_subexpression >	m_left_subexpression_ptr;
	t_counted_ptr< t_subexpression >	m_right_subexpression_ptr;
};

// --------------------------------------------------------------------------
// t_script_binary_expression class template
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
t_script_binary_expression< t_base, t_subexpression_arg >::t_script_binary_expression(
	t_script_binary_expression const &	other )
	:	t_base( other )
{
	if ( other.m_left_subexpression_ptr.get() != 0 )
		m_left_subexpression_ptr = other.m_left_subexpression_ptr->clone();
	
	if ( other.m_right_subexpression_ptr.get() != 0 )
		m_right_subexpression_ptr = other.m_right_subexpression_ptr->clone();
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
inline
typename t_script_binary_expression< t_base, t_subexpression_arg >::t_subexpression const &
t_script_binary_expression< t_base, t_subexpression_arg >::get_left_subexpression() const
{
	assert( m_left_subexpression_ptr.get() != 0 );
	return *m_left_subexpression_ptr;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
inline
typename t_script_binary_expression< t_base, t_subexpression_arg >::t_subexpression const &
t_script_binary_expression< t_base, t_subexpression_arg >::get_right_subexpression() const
{
	assert( m_right_subexpression_ptr.get() != 0 );
	return *m_right_subexpression_ptr;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
bool t_script_binary_expression< t_base, t_subexpression_arg >::read_from_map(
	std::streambuf &	stream,
	int					format_version )
{
	m_left_subexpression_ptr = t_subexpression::reconstruct_from_map( stream, format_version );
	if ( m_left_subexpression_ptr.get() == 0 )
		return false;

	m_right_subexpression_ptr = t_subexpression::reconstruct_from_map( stream, format_version );
	if ( m_right_subexpression_ptr.get() == 0 )
		return false;

	return true;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
bool t_script_binary_expression< t_base, t_subexpression_arg >::read( std::streambuf& stream, int version )
{
	m_left_subexpression_ptr = t_subexpression::reconstruct( stream, version );
	if ( m_left_subexpression_ptr.get() == 0 )
		return false;

	m_right_subexpression_ptr = t_subexpression::reconstruct( stream, version );
	if ( m_right_subexpression_ptr.get() == 0 )
		return false;

	return true;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template < typename t_base, typename t_subexpression_arg >
bool t_script_binary_expression< t_base, t_subexpression_arg >::write( std::streambuf& stream ) const
{
	if (!t_base::write( stream ))
		return false;
	
	if (!m_left_subexpression_ptr->write( stream ))
		return false;

	return m_right_subexpression_ptr->write( stream );
}

#endif // !defined( SCRIPT_COMPOUND_EXPRESSION_H_INCLUDED )
